1 module std.exception; 2 import std.traits; 3 4 void enforce(bool cond, lazy string onThrow, string file = __FILE__, size_t line = __LINE__) pure @trusted 5 { 6 if(cond) 7 throw new Exception(onThrow, null, file, line); 8 } 9 10 void enforce(bool cond, lazy Exception onThrow, string file = __FILE__, size_t line = __LINE__) pure @trusted 11 { 12 if(cond) 13 throw onThrow; 14 } 15 void enforce(T)(bool cond, lazy string onThrow, string file = __FILE__, size_t line = __LINE__) pure @trusted 16 { 17 if(cond) 18 throw new T(onThrow, file, line); 19 } 20 21 22 23 24 25 CommonType!(T[], U[]) overlap(T, U)(T[] a, U[] b) @trusted 26 if (is(typeof(a.ptr < b.ptr) == bool)) 27 { 28 import std.algorithm.comparison : min; 29 30 auto end = min(a.ptr + a.length, b.ptr + b.length); 31 // CTFE requires pairing pointer comparisons, which forces a 32 // slightly inefficient implementation. 33 if (a.ptr <= b.ptr && b.ptr < a.ptr + a.length) 34 { 35 return b.ptr[0 .. end - b.ptr]; 36 } 37 38 if (b.ptr <= a.ptr && a.ptr < b.ptr + b.length) 39 { 40 return a.ptr[0 .. end - a.ptr]; 41 } 42 43 return null; 44 } 45 46 package enum isUnionAliased(T, size_t i) = isUnionAliasedImpl!T(T.tupleof[i].offsetof); 47 private bool isUnionAliasedImpl(T)(size_t offset) 48 { 49 int count = 0; 50 foreach (i, U; typeof(T.tupleof)) 51 if (T.tupleof[i].offsetof == offset) 52 ++count; 53 return count >= 2; 54 } 55 56 57 /** 58 Checks whether a given source object contains pointers or references to a given 59 target object. 60 61 Params: 62 source = The source object 63 target = The target object 64 65 Bugs: 66 The function is explicitly annotated `@nogc` because inference could fail, 67 see $(LINK2 https://issues.dlang.org/show_bug.cgi?id=17084, Bugzilla issue 17084). 68 69 Returns: `true` if `source`'s representation embeds a pointer 70 that points to `target`'s representation or somewhere inside 71 it. 72 73 If `source` is or contains a dynamic array, then, then these functions will check 74 if there is overlap between the dynamic array and `target`'s representation. 75 76 If `source` is a class, then it will be handled as a pointer. 77 78 If `target` is a pointer, a dynamic array or a class, then these functions will only 79 check if `source` points to `target`, $(I not) what `target` references. 80 81 If `source` is or contains a union or `void[n]`, then there may be either false positives or 82 false negatives: 83 84 `doesPointTo` will return `true` if it is absolutely certain 85 `source` points to `target`. It may produce false negatives, but never 86 false positives. This function should be prefered when trying to validate 87 input data. 88 89 `mayPointTo` will return `false` if it is absolutely certain 90 `source` does not point to `target`. It may produce false positives, but never 91 false negatives. This function should be prefered for defensively choosing a 92 code path. 93 94 Note: Evaluating $(D doesPointTo(x, x)) checks whether `x` has 95 internal pointers. This should only be done as an assertive test, 96 as the language is free to assume objects don't have internal pointers 97 (TDPL 7.1.3.5). 98 */ 99 bool doesPointTo(S, T, Tdummy=void)(auto ref const S source, ref const T target) @nogc @trusted pure nothrow 100 if (__traits(isRef, source) || isDynamicArray!S || 101 is(S == U*, U) || is(S == class)) 102 { 103 static if (is(S == U*, U) || is(S == class) || is(S == interface)) 104 { 105 const m = *cast(void**) &source; 106 const b = cast(void*) ⌖ 107 const e = b + target.sizeof; 108 return b <= m && m < e; 109 } 110 else static if (is(S == struct) || is(S == union)) 111 { 112 foreach (i, Subobj; typeof(source.tupleof)) 113 static if (!isUnionAliased!(S, i)) 114 if (doesPointTo(source.tupleof[i], target)) return true; 115 return false; 116 } 117 else static if (isStaticArray!S) 118 { 119 static if (!is(S == void[n], size_t n)) 120 { 121 foreach (ref s; source) 122 if (doesPointTo(s, target)) return true; 123 } 124 return false; 125 } 126 else static if (isDynamicArray!S) 127 { 128 import std.array : overlap; 129 return overlap(cast(void[]) source, cast(void[])(&target)[0 .. 1]).length != 0; 130 } 131 else 132 { 133 return false; 134 } 135 } 136 137 // for shared objects 138 /// ditto 139 bool doesPointTo(S, T)(auto ref const shared S source, ref const shared T target) @trusted pure nothrow 140 { 141 return doesPointTo!(shared S, shared T, void)(source, target); 142 } 143 144 mixin template basicExceptionCtors() 145 { 146 /++ 147 Params: 148 msg = The message for the exception. 149 file = The file where the exception occurred. 150 line = The line number where the exception occurred. 151 next = The previous exception in the chain of exceptions, if any. 152 +/ 153 this(string msg, string file = __FILE__, size_t line = __LINE__, 154 Throwable next = null) @nogc @safe pure nothrow 155 { 156 super(msg, file, line, next); 157 } 158 159 /++ 160 Params: 161 msg = The message for the exception. 162 next = The previous exception in the chain of exceptions. 163 file = The file where the exception occurred. 164 line = The line number where the exception occurred. 165 +/ 166 this(string msg, Throwable next, string file = __FILE__, 167 size_t line = __LINE__) @nogc @safe pure nothrow 168 { 169 super(msg, file, line, next); 170 } 171 } 172 173 immutable(T)[] assumeUnique(T)(T[] array) pure nothrow 174 { 175 return .assumeUnique(array); // call ref version 176 } 177 /// ditto 178 immutable(T)[] assumeUnique(T)(ref T[] array) pure nothrow 179 { 180 auto result = cast(immutable(T)[]) array; 181 array = null; 182 return result; 183 } 184 /// ditto 185 immutable(T[U]) assumeUnique(T, U)(ref T[U] array) pure nothrow 186 { 187 auto result = cast(immutable(T[U])) array; 188 array = null; 189 return result; 190 }